<template>
  <AdVxeModal
    v-bind="$attrs"
    @register="register"
    :id="'send-sms-modal'"
    :title="sendTitle"
    :close-func="handleClose"
    @ok="handleOk"
    width="30%"
  >
    <Form
      class="p-4 enter-x"
      :label-col="labelCol"
      :wrapper-col="wrapperCol"
      :model="formData"
      :rules="getFormRules"
      ref="formRef"
    >
      <FormItem name="PhoneNumber" class="enter-x" :label="t('viewmodal.sendSMS.mobile')">
        <Input
          size="large"
          v-model:value="formData.PhoneNumber"
          :placeholder="t('viewmodal.sendSMS.mobilePlaceholder')"
        >
          <template #prefix>
            <Icon icon="clarity-mobile-phone-solid" />
          </template>
        </Input>
      </FormItem>
      <FormItem name="SmsCode" class="enter-x" :label="t('viewmodal.sendSMS.smsCode')">
        <CountdownInput
          size="large"
          v-model:value="formData.SmsCode"
          :placeholder="t('viewmodal.sendSMS.smsCodePlaceholder')"
          :sendCodeApi="handleSendSMS"
          icon="tabler:device-mobile-message"
        />
      </FormItem>
    </Form>
  </AdVxeModal>
</template>
<script lang="ts" setup>
  import type { PropType } from 'vue';
  import type { Rule } from 'ant-design-vue/es/form';
  import { reactive, unref, ref, toRaw } from 'vue';
  import { AdVxeModal, useModalInner } from '@/components/AdVxeModal';
  import { Form, Input } from 'ant-design-vue';
  import { RuleObject } from 'ant-design-vue/lib/form/interface';
  import { CountdownInput } from '@/components/CountDown';
  import Icon from '@/components/Icon/Icon.vue';

  import { useI18n } from '@/hooks/web/useI18n';
  import { useMessage } from '@/hooks/web/useMessage';
  import { isFunction } from '@/utils/is';
  import { propTypes } from '@/utils/propTypes';

  import { VerifyCodeConfirmDto } from '@/api/sms/model';
  import { sendSmsVerifyCode, checkSmsVerifyCode } from '@/api/sms';
  import { isMobileNumber } from '@/enums/regexEnum';
  import { checkPhoneNumberExists } from '@/api/identity';

  /** 发送短信DTO */
  export interface SendSMSDto {
    /** 手机号码 */
    PhoneNumber: string;
    /** 短信验证码 */
    SmsCode: string;
    /** 短信验证码编号 */
    SmsCodeId: string;

    /** 验证码 */
    VerifyCode?: string;
    /** 验证码编号 */
    VerifyCodeId?: string;
  }

  const FormItem = Form.Item;

  defineOptions({ name: 'SendSMS' });
  const props = defineProps({
    /** 标题 */
    sendTitle: propTypes.string.def(''),
    /** 验证手机号是否存在，默认 undefined */
    checkMobileExist: propTypes.bool.def(undefined),
    /** 确定前回调，返回true关闭窗体 */
    beforeOkFunc: {
      type: Function as PropType<(data: SendSMSDto) => Promise<boolean>>,
      default: null,
    },
  });

  const { t } = useI18n();
  const { createMessage } = useMessage();
  const formRef = ref();

  const formData: SendSMSDto = reactive({
    PhoneNumber: '',
    SmsCode: '',
    SmsCodeId: '',
  });

  const [register, { closeModal, changeOkLoading }] = useModalInner((data) => {
    formData.PhoneNumber = data.mobile;
    formData.SmsCode = '';
    formData.SmsCodeId = '';
  });

  /** 获取表单规则 */
  const getFormRules: Record<string, Rule[]> = {
    PhoneNumber: [
      {
        required: true,
        validator: async (_: RuleObject, value: string) => {
          if (!value) {
            return Promise.reject(t('viewmodal.sendSMS.mobilePlaceholder'));
          }
          if (!isMobileNumber(value)) {
            return Promise.reject(t('viewmodal.sendSMS.mobileFormatError'));
          }
          if (props.checkMobileExist !== undefined) {
            const isExist = await checkPhoneNumberExists(value);
            if (props.checkMobileExist && isExist) {
              return Promise.reject(t('viewmodal.sendSMS.mobileExisted'));
            }
            if (!props.checkMobileExist && !isExist) {
              return Promise.reject(t('viewmodal.sendSMS.mobileNotExisted'));
            }
          }
          return Promise.resolve();
        },
        trigger: 'change',
      },
    ],
    SmsCode: [
      {
        required: true,
        validator: async (_: RuleObject, value: string) => {
          if (!value) {
            return Promise.reject(t('viewmodal.sendSMS.smsCodePlaceholder'));
          }
          if (value === undefined || value === null || value === '') {
            return Promise.reject(t('viewmodal.sendSMS.smsCodeInvalid'));
          }
          const dto: VerifyCodeConfirmDto = {
            PhoneNumber: formData.PhoneNumber,
            Code: value,
            CodeId: formData.SmsCodeId,
          };
          if (!(await checkSmsVerifyCode(dto))) {
            return Promise.reject(t('viewmodal.sendSMS.smsCodeInvalid'));
          }
          return Promise.resolve();
        },
        trigger: 'change',
      },
    ],
  };

  /** 验证表单 */
  const validForm = async () => {
    const form = unref(formRef);
    if (!form) return;
    const data = await form.validate();
    return data;
  };

  /** 处理发送短信 */
  async function handleSendSMS() {
    if (
      formData.PhoneNumber === undefined ||
      formData.PhoneNumber === null ||
      formData.PhoneNumber === ''
    ) {
      createMessage.error(t('viewmodal.sendSMS.mobilePlaceholder'));
      return false;
    }
    if (!isMobileNumber(formData.PhoneNumber)) {
      createMessage.error(t('viewmodal.sendSMS.mobileFormatError'));
      return false;
    }
    const dto = toRaw({ PhoneNumber: formData.PhoneNumber });
    const ajaxResult = await sendSmsVerifyCode(dto);
    formData.SmsCodeId = ajaxResult.Data as string;
    return true;
  }

  /** 处理确定 */
  async function handleOk() {
    const { beforeOkFunc } = props;
    const data = await validForm();
    if (!data) return;

    if (beforeOkFunc && isFunction(beforeOkFunc)) {
      changeOkLoading(true);
      try {
        const canClose = await beforeOkFunc(formData);
        if (canClose) {
          clearFormData();
          closeModal();
        }
      } finally {
        changeOkLoading(false);
      }
    } else {
      clearFormData();
      closeModal();
    }
  }

  /** 处理取消 */
  async function handleClose() {
    clearFormData();
    return true;
  }

  /** 清除表单数据 */
  function clearFormData() {
    formData.PhoneNumber = '';
    formData.SmsCode = '';
    formData.SmsCodeId = '';
  }

  const labelCol = { span: 6 };
  const wrapperCol = { span: 16 };
</script>
